package com.mindata.blockchain.core.service.sqliteChecker;

import com.mindata.blockchain.ApplicationContextProvider;
import com.mindata.blockchain.block.Block;
import com.mindata.blockchain.block.Instruction;
import com.mindata.blockchain.block.Operation;
import com.mindata.blockchain.core.event.RecoveryListEvent;
import com.mindata.blockchain.core.manager.DbBlockManager;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

public class BaseCheckService {

    @Resource
    private DbBlockManager dbBlockManager;
    private Instruction instruction;

    public HashMap<String,String> check(String table, HashMap<String,String> map) {

        Block block = dbBlockManager.getLastBlock();
        String json, instructionId;
        ArrayList<String> checkedList = new ArrayList<>();
        HashMap<String,String> errorList = new HashMap<>();

        // 从后往前遍历所有instructionId
        do{
            for(int i=block.getBlockBody().getInstructions().size()-1; i>=0; i--){
                instruction = block.getBlockBody().getInstructions().get(i);
                if(instruction.getTable().equals(table)){
                    instructionId = instruction.getInstructionId();
                    // 保存已遍历的instructionId，不重复遍历相同的Id，保证遍历并操作的Id所对应的内容都是最新的
                    if(!checkedList.contains(instructionId)){
                        checkedList.add(instructionId);
                        json = instruction.getJson();
                        if(map.get(instructionId)==null){
                            // 在数据库中找不到该记录，即数据库中该记录被删除
                            errorList.put(instructionId,json);
                            ApplicationContextProvider.publishEvent(new RecoveryListEvent("",instructionId,instruction,Operation.ADD));
                        }
                        else{
                            if(!json.equals(map.get(instructionId))) {
                                // 内容被篡改
                                errorList.put(instructionId,json);
                                ApplicationContextProvider.publishEvent(new RecoveryListEvent("",instructionId,instruction,Operation.UPDATE));
                            }
                        }
                    }
                }
            }
            if(!block.toString().equals(dbBlockManager.getFirstBlock().toString())) {
                block = dbBlockManager.getBlockByHash(block.getBlockHeader().getHashPreviousBlock());
            }
            else {
                Iterator iterator = map.entrySet().iterator();
                while (iterator.hasNext()){
                    HashMap.Entry entry = (HashMap.Entry)iterator.next();
                    Object messageId = entry.getKey();
                    if(!checkedList.contains(messageId)) {
                        errorList.put((String) messageId, null);
                        Instruction nullInstruction = new Instruction();
                        nullInstruction.setInstructionId((String)messageId);
                        nullInstruction.setTable(instruction.getTable());
                        nullInstruction.setPublicKey(instruction.getPublicKey());
                        nullInstruction.setOldJson("{\"publicKey\":\"" + instruction.getPublicKey() + "\"}");
                        ApplicationContextProvider.publishEvent(new RecoveryListEvent("", (String) messageId,nullInstruction,Operation.DELETE));
                    }

                }
                return errorList;
            }
        }while(true);


    }


}
